# -*- coding: utf-8 -*-

from pydantic import BaseModel

from fastapi import Depends, HTTPException, status
from fastapi.security import OAuth2PasswordBearer

from passlib.context import CryptContext
from jwt.exceptions import InvalidTokenError
import jwt

from datetime import datetime, timedelta

from app.config import settings

oauth2_scheme = OAuth2PasswordBearer(tokenUrl=settings.SWAGGER_UI_OAUTH2_REDIRECT_URL)

class Token(BaseModel):
    access_token: str
    refresh_token: str
    token_type: str

# 密码
pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")

def password_hash(password: str):
    '''
    密码加密
    '''
    return pwd_context.hash(password)

def virify_password(plain_password, hashed_password):
    '''
    验证密码
    plain_password: 明文密码
    hashed_password: 加密后的密码
    '''
    return pwd_context.verify(plain_password, hashed_password)

def create_token(data: dict, expires_delta: int | None = None):
    '''
    创建token
    '''
    to_encode_data = data.copy()
    if expires_delta:
        expire = datetime.utcnow() + timedelta(minutes=expires_delta)
    else:
        expire = datetime.utcnow() + timedelta(minutes=15)
    to_encode_data.update({"exp": expire})
    return jwt.encode(to_encode_data, settings.JWT_SECRET_KEY, algorithm=settings.JWT_ALGORITHM)


def create_access_token(data: dict):
    '''
    创建 access token
    '''
    return create_token(data, expires_delta=settings.JWT_ACCESS_TOKEN_EXPIRE_MINUTES)

def create_refresh_token(data: dict):
    '''
    创建 refresh token
    '''
    return create_token(data, expires_delta=settings.JWT_REFRESH_TOKEN_EXPIRE_MINUTES)

async def get_token_data(token: str = Depends(oauth2_scheme)):
    '''
    获取token数据
    '''
    try:
        return jwt.decode(token, settings.JWT_SECRET_KEY, algorithms=[settings.JWT_ALGORITHM])
    except jwt.ExpiredSignatureError:
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="凭证已证过期",
            headers={"WWW-Authenticate": f"Bearer {token}"},
        )

    except jwt.InvalidTokenError:
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="无效凭证",
            headers={"WWW-Authenticate": f"Bearer {token}"},
        )

    except (PyJWTError, ValidationError):
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="无效凭证",
            headers={"WWW-Authenticate": f"Bearer {token}"},
        )
